perm filename MFDD.FAI[MF,DEK] blob
sn#748734 filedate 1984-04-03 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00006 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 TITLE MFDD P BEGX BEGY XSIZE YSIZE XWORDS EXCT FNCN CHNL COLM HILIN LOLIN DDJMP DDPROG DDEND DDLEN NDDCW DD4TH ROWTAB CMDBLK LOWROW
C00006 00003 INITSCREEN
C00007 00004 BEGIN BLANKRECTANGLE X0 X1 Y0 Y1 T0 T1 T2 T3 T4 BLANK1 BLANK2
C00010 00005 BEGIN PAINTROW R B A N X0 X1 T0 T1 T2 T3 PAINT1 PAINT2 PAINT3 PAINTX
C00013 00006 BEGIN UPDSCREEN T T1
C00016 ENDMK
C⊗;
TITLE MFDD ;⊗ P BEGX BEGY XSIZE YSIZE XWORDS EXCT FNCN CHNL COLM HILIN LOLIN DDJMP DDPROG DDEND DDLEN NDDCW DD4TH ROWTAB CMDBLK LOWROW
;DataDisc display routines for MetaFont, callable from Hedrick Pascal (PSC).
;Specifications by Donald Knuth, code by Joe Weening, April 1984.
;Ideas borrowed from display code in DVIDD and WHOPHN.
TWOSEG
↓P←17 ;Our friendly push-down pointer
;Our screen dimensions should have the following relation to MF's:
; screen_width = XSIZE - BEGX
; screen_depth = YSIZE
;The 40 text lines (480 graphics lines) of the DD screen are apportioned
;as follows:
; 2 lines System Wholine
; up to 38 lines Graphics display
; remaining lines Page printer
;The page printer is made as large as possible, based on the amount of
;graphics display selected by the user, but is always at least 3 lines
;of text. (If this overlaps the display, then display and text output
;will overwrite each other.)
BEGX←←=8 ;First pixel to use in X-direction
BEGY←←=24 ;First pixel to use in Y-direction
XSIZE←←=500 ;Number of pixels in X-direction
YSIZE←←=38*=12 ;Number of pixels in Y-direction
;(must be a multiple of 4)
XWORDS←←<XSIZE+=31>/=32 ;Words per row in DD program (32 bits per word)
DEFINE CW(C1,B1,C2,B2,C3,B3)<<BYTE (8)B1,B2,B3(3)C1,C2,C3>!4>
EXCT←←0 ;Execute
FNCN←←1 ;Function
CHNL←←2 ;Channel
COLM←←3 ;Column select
HILIN←←4 ;Set high 5 bits of line adr
LOLIN←←5 ;Set low 4 bits of line adr
DDJMP←←20 ;Opcode for DD jump instruction
;Here we set up DDPROG and ROWTAB so that the lines in DDPROG are 0,4,8,...,
;then 1,5,9,..., then 2,6,10,..., then 3,7,11,..., and ROWTAB+I points to
;the line word in line I, for 0≤I<YSIZE.
RELOC 0 ;For data
DDPROG:
;LINEWD of first line in DDPROG is changed by code at SHOWDD.
FOR I←0,3<
FOR J←I,YSIZE-1,4<
CW 0,0,HILIN,<<BEGY+J>⊗-4>,LOLIN,<<BEGY+J>&17> ;LINEWD
CW FNCN,7,FNCN,7,COLM,1 ;COLMWD
REPEAT XWORDS,<
2>
>;FOR J
>;FOR I
CW 0,0,CHNL,0,CHNL,0 ;Execute the last line
DDEND: 0 ;Make sure DD prog ends with a halt
DDLEN←←.-DDPROG
NDDCW←←2 ;Number of extra DD CWs per graphics line (LINEWD,COLMWD)
DD4TH←←YSIZE*<NDDCW+XWORDS>/4 ;Size of each 1/4th of the DD program
ROWTAB: FOR I←0,YSIZE/4-1
< FOR J←I,YSIZE-1,YSIZE/4
< DDPROG+J*<NDDCW+XWORDS>+NDDCW
>>
CMDBLK: DDPROG ;Command block for DDUPG to display DDPROG
DDLEN
0
0
LOWROW: BLOCK 1 ;Lowest row number used
RELOC 400000 ;For code
;INITSCREEN
;function init_screen: boolean; extern;
;
;Returns TRUE if we're on a DD terminal; FALSE otherwise.
INITSCREEN↑:
SETZM LOWROW ;Set minimum display size
SETO 1,
MOVNM 1,1(P) ;Set return to TRUE (=1 in Pascal)
GETLIN 1 ;Get our line characteristics
CAME 1,[-1] ;Skip if detached
TLNN 1,20000 ;Skip if a DD
SETZM 1(P) ;Not a DD, return FALSE
MOVEI 1,CHNL ;Put CHNL cmd
DPB 1,[POINT 3,DDPROG,26] ;in first word of DD prog
POPJ P,
BEGIN BLANKRECTANGLE ;⊗ X0 X1 Y0 Y1 T0 T1 T2 T3 T4 BLANK1 BLANK2
;procedure blank_rectangle(left_col,right_col:screen_col;
; top_row,bot_row:screen_row); extern;
;
;Whiten all pixels that lie in columns left_col through right_col-1, inclusive,
;of rows top_row through bot_row-1.
X0←2 ;left_col
X1←3 ;right_col
Y0←4 ;top_row
Y1←5 ;bot_row
T0←6 ;Scratch ACs
T1←7
T2←10
T3←11
T4←12
BLANKRECTANGLE↑:
CAMLE Y1,LOWROW ;Increase display size if necessary
MOVEM Y1,LOWROW
CAMGE X0,X1 ;Test easy cases
CAML Y0,Y1
POPJ P,
ADDI X0,BEGX ;Adjust X0 and X1 to our left edge
ADDI X1,BEGX-1 ;and subtract 1 from X1 while we're at it
MOVE T0,X0
LSH T0,-5 ;Get X0's word position in T0
ANDI X0,37 ;Bit position in X0
MOVN T2,X0 ;Negate
SETO X0, ;Get an all 1's mask
LSH X0,(T2) ;Make mask for first column
TRZ X0,17 ;Zero non-data bits
MOVE T1,X1
LSH T1,-5 ;Get X1's word position in T1
ANDI X1,37 ;Bit position in X1
MOVN T2,X1 ;Negate
SETO X1, ;Get an all 1's mask
LSH X1,-1(T2) ;Make mask for last column
MOVE T2,X0 ;Start with mask for first column
BLANK1: CAMN T0,T1 ;Is this the last column?
ANDCM T2,X1 ;Yes, mask appropriately
MOVE T4,Y0 ;Start T4 at first row
BLANK2: MOVE T3,ROWTAB(T4) ;Point to row in DD prog
ADD T3,T0 ;Point to proper word
ANDCAM T2,(T3) ;Clear selected bits
CAIGE T4,-1(Y1) ;All done this column?
AOJA T4,BLANK2 ;No, do another row in column
MOVE T2,[777777,,777760];Set mask for next column
CAMGE T0,T1 ;All done?
AOJA T0,BLANK1 ;No, do another column
POPJ P,
BEND BLANKROW
BEGIN PAINTROW ;⊗ R B A N X0 X1 T0 T1 T2 T3 PAINT1 PAINT2 PAINT3 PAINTX
;procedure paintrow(r:screen_row; b:pixel_color; var a:trans_spec;
; n:screen_column);
;In row r, alternately clear and blacken pixels (starting with the operation
;specified by b), in columns a[0]..a[1]-1, a[1]..a[2]-1, ..., a[n-1]..a[n]-1.
R←2 ;Parameters
B←3
A←4
N←5
X0←6 ;Temporary ACs
X1←7
T0←10
T1←11
T2←12
T3←13
PAINTROW↑:
CAMLE R,LOWROW ;Increase display size if necessary
MOVEM R,LOWROW
PAINT1: DMOVE X0,(A) ;Get next two values from A array into X0,X1
ADDI X0,BEGX ;Adjust X0 and X1 to our left edge
ADDI X1,BEGX-1 ;and subtract 1 from X1 while we're at it
CAMLE X0,X1 ;Make sure there's work to do
JRST PAINT3 ;If not, skip to next operation
MOVE T0,X0
LSH T0,-5 ;Get X0's word position in T0
ANDI X0,37 ;Bit position in X0
MOVN T2,X0 ;Negate
SETO X0, ;Get an all 1's mask
LSH X0,(T2) ;Make mask for first column
TRZ X0,17 ;Zero non-data bits
MOVE T1,X1
LSH T1,-5 ;Get X1's word position in T1
ANDI X1,37 ;Bit position in X1
MOVN T2,X1 ;Negate
SETO X1, ;Get an all 1's mask
LSH X1,-1(T2) ;Make mask for last column
MOVE T2,X0 ;Start with mask for first column
PAINT2: CAMN T0,T1 ;Is this the last column?
ANDCM T2,X1 ;Yes, mask appropriately
MOVE T3,ROWTAB(R) ;Point to row in DD prog
ADD T3,T0 ;Point to proper word
XCT PAINTX(B) ;Clear or blacken selected bits
MOVE T2,[777777,,777760];Set mask for next column
CAMGE T0,T1 ;All done?
AOJA T0,PAINT2 ;No, do another column
PAINT3: MOVEI A,1(A) ;Advance to next operation
TRC B,1 ;Complement B
SOJG N,PAINT1 ;Continue until done
POPJ P,
PAINTX: ANDCAM T2,(T3) ;Clear selected bits (B=0)
IORM T2,(T3) ;Blacken selected bits (B=1)
BEND PAINTROW
BEGIN UPDSCREEN ;⊗ T T1
;procedure updscreen; extern;
;
;Display the DD program.
T←2 ;Temporary ACs
T1←3
UPDSCREEN↑:
MOVE T,LOWROW ;Get lowest row displayed
ADDI T,BEGY+=11 ;Convert to DD row, round up for divide
IDIVI T,=12 ;Get text line number of first PP line
CAILE T,=37 ;Always have at least 3 lines in PP
MOVEI T,=37
PUSH P,T ;Save for DPYSIZ below
LSH T,7
IDIV T,[-5]
DPYPOS 1000(T) ;Position page printer
POP P,T
MOVNI T,-=40(T) ;40 - T = number of lines in page printer
LSH T,9
DPYSIZ 1(T) ;Set number of glitches, 1 line per glitch
;Now replace DD command words by jumps to shorten the display
;program if necessary.
MOVE T,LOWROW ;Last row being shown
CAIL T,YSIZE-4 ;Need to shorten display?
JRST [ DDUPG CMDBLK ;No, just output it
POPJ P,]
LSH T,-2 ;Divide by 4
ADDI T,1
IMULI T,NDDCW+XWORDS ;Size of each 1/4th of the DD prog being used
FOR I←0,3<
PUSH P,DDPROG+I*DD4TH(T) ;Save word being clobbered
MOVE T1,[DDPROG+<I+1>*DD4TH,,DDJMP] ;Jump to next 1/4th of full DD prog
MOVEM T1,DDPROG+I*DD4TH(T) ;Insert the jump instruction
>;FOR I
DDUPG CMDBLK ;Do the display
FOR I←3,0,-1<
POP P,DDPROG+I*DD4TH(T) ;Restore altered words
>;FOR I
POPJ P,
BEND UPDSCREEN
END